#ifndef	__ASSEMBLER__
#define	__ASSEMBLER__
#endif

// This file is the asm boot loader for EKOS

#include <inc/memlayout.h>
#include <inc/mmu.h>

#define	RELOC(x)        ((x) - KBASE)

	      //    for multiboot header

#define	MULTIBOOT_PAGE_ALIGN   (1<<0)
#define	MULTIBOOT_MEMORY_INFO  (1<<1)
#define	MULTIBOOT_HEADER_MAGIC (0x1BADB002)
#define	MULTIBOOT_HEADER_FLAGS (MULTIBOOT_MEMORY_INFO | MULTIBOOT_PAGE_ALIGN)
#define	CHECKSUM               (-(MULTIBOOT_HEADER_MAGIC + MULTIBOOT_HEADER_FLAGS))

	      .text
_kstart:
	      .code32
	      
	      //    The Multiboot header
	      
	      .align 4
	      .long MULTIBOOT_HEADER_MAGIC
	      .long MULTIBOOT_HEADER_FLAGS
	      .long CHECKSUM
	      
	      .long _kstart
	      .long _text
	      .long _bss
	      .long _end
	      .long _start

	      //    boot loader code begins here

	      .globl _start
_start:
	      //    Load the new boot stage gdt

	      movl  $RELOC(boot_gdt_desc), %eax
	      lgdt  (%eax)

	      //    Reload all segment register

	      movl  $GD_KERN_DATA, %eax
	      movw  %ax, %ds
	      movw  %ax, %es
	      movw  %ax, %ss
	      ljmp  $GD_KERN_TEXT, $relocated

relocated:
	      //    initial boot stage stack
	      
	      movl  $0x0, %ebp
	      movl  $(boot_stack_top), %esp

		  //	Call the c init procedure for further initailization
	      call  kinit
	      
	      .align PAGE_SIZE
	      //    force page alignment
	      
	      .globl boot_vpd
boot_vpd:	      
	      .space PAGE_SIZE

	      //    boot stack space
	      .globl boot_stack
boot_stack:
	      .space KSTACK_SIZE
	      .globl boot_stack_top
boot_stack_top:

	      .align 4
	      //    force 4 byte alignment
	      
boot_gdt:
	      SEG_NULL
	      SEG(STA_X | STA_R, -KBASE, 0xffffffff)
	      SEG(STA_W, -KBASE, 0xffffffff)
boot_gdt_desc:
	      //    sizeof(boot_gdt) - 1
	      .word 0x17
	      //    address
	      .long RELOC(boot_gdt)
